#include <iostream>
#include <thread>
#include <atomic>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>

namespace NetWork{
    const int defaultsockfd = -1;
    const int backlog = 5;
    const int defaultport = 8080;
    const int buffersize = 1024;

    enum {
        SocketError = 1,
        BindError,
        ListenError
    };

    class TcpServer{
        public:
            TcpServer():server_fd(defaultsockfd), is_running(false) {}
            
            ~TcpServer() {  Stop();  }
    
            void Start() {
                if(is_running)  // 服务器已经成功运行
                    return ;
    
                is_running = true;
                server_thread = std::thread([this](){
                    server_loop();
                });
                std::cout << "server running" << std::endl;
                return ;
            }
            
            void Stop() {
                if(!is_running) // 服务器已经停止运行
                    return ;
                
                is_running = false;
                if(server_thread.joinable()) {
                    server_thread.join();
                }
            }
        private:
            void server_loop() {
                server_fd = ::socket(AF_INET, SOCK_STREAM, 0);
                if(server_fd < 0) {
                    std::cout << "create error" << std::endl;
                    exit(SocketError) ;
                }
                std::cout << "socket success" << std::endl;

                struct sockaddr_in local;
                memset(&local, 0, sizeof(local));
                local.sin_family = AF_INET;
                local.sin_addr.s_addr = INADDR_ANY;
                local.sin_port = htons(defaultport);
                int ret = ::bind(server_fd, (struct sockaddr*)(&local), sizeof(local));
                if(ret < 0) {
                    std::cout << "bind error" << std::endl;
                    close(server_fd);
                    exit(BindError);
                }
                std::cout << "bind success" << std::endl;

                ret = ::listen(server_fd, backlog);
                if(ret < 0) {
                    std::cout << "listen error" << std::endl;
                    close(server_fd);
                    exit(ListenError);
                }
                std::cout << "listen success" << std::endl;

                // 创建子线程，接受客户端连接
                while(is_running) {
                    struct timeval tv;
                    fd_set readfds;
                    FD_ZERO(&readfds);
                    FD_SET(server_fd, &readfds);
                    tv.tv_sec = 1;

                    int ret = select(server_fd + 1, &readfds, NULL, NULL, &tv);
                    if(ret < 0) {
                        std::cout << "select errr";
                        break;
                    }
                    else if(ret == 0) {
                        continue;   // 超时
                    }

                    // 接受连接
                    int new_socket = defaultsockfd;
                    int locallen = sizeof(local);
                    new_socket = accept(server_fd, (struct sockaddr*)(&local), (socklen_t*)(&locallen));
                    if(new_socket < 0) {
                        std::cout << "accept error" << std::endl;
                        continue;
                    }
                    std::cout << "accept success" << std::endl;

                    // 创建新线程处理客户端
                    std::thread client_thread([this, new_socket](){
                        hand_cllient(new_socket);
                    });
                    client_thread.detach();
                }

                close(server_fd);
                std::cout << "server stopped" << std::endl;
            }
            
            // 处理客户端连接
            void hand_cllient(int client_socket) {
                char buffer[buffersize] = {0};

                while(true) {
                    memset(buffer, 0, sizeof(buffer));
                    ssize_t n = recv(client_socket, buffer, sizeof(buffer), 0);
                    
                    if(n <= 0)  {
                        break;
                    }

                    std::cout << "Received: " << buffer;

                    send(client_socket, buffer, n, 0);
                }

                close(client_socket);
                std::cout << "client disconnected" << std::endl;
            }

            int server_fd;                  // 服务器套接字
            std::atomic<bool> is_running;   // 服务器运行时状态
            std::thread server_thread;      // 服务器线程
    };
}

